const child_process = require('child_process');
const os = require('os');
const path = require('path');
const fs = require('fs');

const spawnPromise = function(commond, params, cwd){
    console.log('执行：', commond, params, cwd);
    let _log = '';
    return new Promise((resolve, reject)=>{
        let ls = child_process.spawn(commond, params, {cwd: cwd});
        ls.stdout.on('data', data=>{
            _log += data;
            console.log('stdout data: ', data);
        });
        ls.stderr.on('data', data => {
            // reject(_log);
            _log += data;
            console.log('stderr data: ', data);
        })
        ls.on('close', code => {
            console.log(_log);
            resolve(_log);
        })
    });
}

const execPromise = function(commond){
    console.log('执行：', commond);
    let _log = '';
    return new Promise((resolve, reject)=>{
        let ls = child_process.exec(commond);
        ls.stdout.on('data', data=>{
            _log += data;
            console.log(data);
        });
        ls.stderr.on('data', data => {
            // reject(_log);
            _log += data;
            console.log(data);
        })
        ls.on('close', code => {
            console.log(_log);
            resolve(_log);
        })
    });
}

const loopDirs = function(dir,arr){
    let files = fs.readdirSync(dir);
    for  (let file of files){
      if (!file.match(/.proto$/)){
        continue;
      }
      let fullpath = path.join(dir,file);
      let stat = fs.statSync(fullpath);
      if (stat.isFile()){
         arr.push(file.split('.')[0]);
      }else if (stat.isDirectory()){
         loopDirs(fullpath,arr);
      }
    }
  
  }

const protoTool = {
    config:{
        protoPath: "",
        change: true,     
        protoNames: []
    }
};

protoTool.execPromise = execPromise;
/**
 * 
 * @param {*} options {
 *  protoPath: ''  // .proto文件所在位置
 *  protoNames: [] // .proto文件名称
 *  change: false  // 是否替换$protobuf加载方式
 * }
 */
protoTool.setConfig = function(options){
    this.config = options;
}

protoTool.run = async function(){
    let len = this.config["protoNames"].length || 0;
    // 如果未配置文件名，则默认扫描该文件夹下的所有的.proto文件
    if(len === 0){
        let files = [];
        loopDirs(this.config["protoPath"], files);
        this.config["protoNames"] = files;
    }
    
    for(let i = 0; i < this.config["protoNames"].length; i++){
        let fileName = this.config["protoNames"][i];
        await this.runSingle(fileName);
    }
}

protoTool.runSingle = async function(fileName){
    // 安装公共处理模块
    // await spawnPromise('npm', ['install', 'protobufjs', '-g'], os.homedir());
    // // 处理指定的proto模块
    let pathDir = this.config["protoPath"];
    let toPath = this.config["toPath"]
    let animJsProto = path.join(toPath, `${fileName}.js`);
    await execPromise(`pbjs -t static-module -w commonjs -o ${animJsProto} ${path.join(pathDir, `${fileName}`)}`);
    
    if(this.config.change){
        // 修改文件夹内容
        let scriptData = fs.readFileSync(animJsProto, {encoding: 'utf-8'});
        scriptData = scriptData.replace('require("protobufjs/minimal")', 'protobuf');
        fs.writeFileSync(animJsProto, scriptData);
    }
}

protoTool.run2 = async function(){
    let len = this.config["protoNames"].length || 0;
    // 如果未配置文件名，则默认扫描该文件夹下的所有的.proto文件
    if(len === 0){
        let files = [];
        loopDirs(this.config["protoPath"], files);
        this.config["protoNames"] = files;
    }
    
    let file_names = '';
    let dtsPath = '';
    let pathDir = this.config["protoPath"];
    let toPath = this.config["toPath"];

    for(let i = 0; i < this.config["protoNames"].length; i++){
        let fileName = this.config["protoNames"][i];
        let filepath = path.join(pathDir, `${fileName}`) + ' ';
        let animJsProto = path.join(toPath, `${fileName}.js`) + ' ';
        file_names += filepath;
        dtsPath += animJsProto;
    }
    await this.runSingle2(file_names,'hsxyproto',dtsPath);
}

protoTool.runSingle2 = async function(filepath,outName,dtsPath){
    // 安装公共处理模块
    // await spawnPromise('npm', ['install', 'protobufjs', '-g'], os.homedir());
    // // 处理指定的proto模块
    let toPath = this.config["toPath"]
    let animJsProto = path.join(toPath, `${outName}.js`);
    await execPromise(`pbjs -t static-module -w commonjs -o ${animJsProto} ${filepath}`);
    
    if(this.config.change){
        // 修改文件夹内容
        let scriptData = fs.readFileSync(animJsProto, {encoding: 'utf-8'});
        scriptData = scriptData.replace('require("protobufjs/minimal")', 'protobuf');
        fs.writeFileSync(animJsProto, scriptData);
    }

    await execPromise(`pbts -o ${path.join(toPath, `${outName}.d.ts`)} ${dtsPath}`);
}

protoTool.run3 = async function(){
    let len = this.config["protoNames"].length || 0;
    // 如果未配置文件名，则默认扫描该文件夹下的所有的.proto文件
    if(len === 0){
        let files = [];
        loopDirs(this.config["protoPath"], files);
        this.config["protoNames"] = files;
    }
    
    for(let i = 0; i < this.config["protoNames"].length; i++){
        let fileName = this.config["protoNames"][i];
        await this.runSingle3(fileName);
    }
}

protoTool.runSingle3 = async function(fileName){
    let toPath = this.config["toPath"]
    let animJsProto = path.join(toPath, `${fileName}.js`);
    await fs.unlinkSync(animJsProto);
}

module.exports = protoTool;
